home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / mesademos / tess_demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  7.5 KB  |  377 lines

  1.  
  2. /* tess_demo.c */
  3.  
  4. /* A demo of the GLU polygon tesselation functions written by Bogdan Sikorski. */
  5.  
  6. /* Bug fixes by Mark Kilgard 11/8/96 */
  7.  
  8. #include <GL/glut.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. /* Win32 calling conventions. */
  14. #ifndef CALLBACK
  15. #define CALLBACK
  16. #endif
  17.  
  18. #define MAX_POINTS 200
  19. #define MAX_CONTOURS 50
  20. #define HALF_WIDTH 5     /* half of the width of a grid box */
  21.  
  22. int menu;
  23. typedef enum {
  24.   QUIT, TESSELATE, CLEAR
  25. } menu_entries;
  26. typedef enum {
  27.   DEFINE, TESSELATED
  28. } mode_type;
  29. struct {
  30.   GLint p[MAX_POINTS][2];
  31.   GLuint point_cnt;
  32. } contours[MAX_CONTOURS];
  33. int contour_cnt;
  34. GLsizei width, height;
  35. mode_type mode;
  36.  
  37. #ifdef GLU_VERSION_1_2
  38. typedef struct listmem {
  39.    GLint *data;
  40.    struct listmem *next;
  41. } ListMem;
  42.  
  43. ListMem root;
  44. #endif
  45.  
  46. void CALLBACK
  47. my_error(GLenum err)
  48. {
  49.   int len, i;
  50.   const char *str;
  51.  
  52.   glColor3f(0.9, 0.9, 0.9);
  53.   glRasterPos2i(5, 5);
  54.   str = (char *) gluErrorString(err);
  55.   len = (int) strlen(str);
  56.   for (i = 0; i < len; i++)
  57.     glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[i]);
  58. }
  59.  
  60. #ifdef GLU_VERSION_1_2
  61. /* ARGSUSED */
  62. void CALLBACK
  63. myCombine(GLdouble coords[3], void *d[4], GLfloat w[4], void **dataOut)
  64. {
  65.    ListMem *ptr = &root;
  66.    while (ptr->next) ptr = ptr->next;
  67.    ptr->next = malloc(sizeof(ListMem));
  68.    ptr = ptr->next;
  69.    ptr->next = 0;
  70.    ptr->data = malloc(3 * sizeof(GLint));
  71.    ptr->data[0] = (GLint) coords[0];
  72.    ptr->data[1] = (GLint) coords[1];
  73.    ptr->data[2] = (GLint) coords[2];
  74.    *dataOut = ptr->data;
  75. }
  76. #endif
  77.  
  78. void 
  79. set_screen_wh(GLsizei w, GLsizei h)
  80. {
  81.   width = w;
  82.   height = h;
  83. }
  84.  
  85. void 
  86. tesse(void)
  87. {
  88.   static GLUtriangulatorObj *tobj = NULL;
  89.   GLdouble data[3];
  90.   int i, j, point_cnt;
  91.  
  92.   if (tobj == NULL) {
  93.     tobj = gluNewTess();
  94.   }
  95.   if (tobj != NULL) {
  96.     glClear(GL_COLOR_BUFFER_BIT);
  97.     glColor3f(0.7, 0.5, 0.0);
  98.     gluTessCallback(tobj, GLU_BEGIN, (void (CALLBACK*)())glBegin);
  99.     gluTessCallback(tobj, GLU_END, (void (CALLBACK*)())glEnd);
  100.     gluTessCallback(tobj, GLU_ERROR, (void (CALLBACK*)()) my_error);
  101.     gluTessCallback(tobj, GLU_VERTEX, (void (CALLBACK*)()) glVertex2iv);
  102. #ifdef GLU_VERSION_1_2
  103.     root.data = 0;
  104.     root.next = 0;
  105.     gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK*)()) myCombine);
  106. #endif
  107.     gluBeginPolygon(tobj);
  108.     for (j = 0; j <= contour_cnt; j++) {
  109.       point_cnt = contours[j].point_cnt;
  110.       gluNextContour(tobj, GLU_UNKNOWN);
  111.       for (i = 0; i < point_cnt; i++) {
  112.         data[0] = (GLdouble) (contours[j].p[i][0]);
  113.         data[1] = (GLdouble) (contours[j].p[i][1]);
  114.         data[2] = 0.0;
  115.         gluTessVertex(tobj, data, contours[j].p[i]);
  116.       }
  117.     }
  118.     gluEndPolygon(tobj);
  119.     mode = TESSELATED;
  120.   }
  121. #ifdef GLU_VERSION_1_2
  122.   {
  123.     ListMem *fptr = root.next;
  124.     ListMem *tmp;
  125.     while (fptr) {
  126.       tmp = fptr->next;
  127.       free(fptr->data);
  128.       free(fptr);
  129.       fptr = tmp;
  130.     }
  131.   }
  132. #endif
  133. }
  134.  
  135. void 
  136. left_down(int x1, int y1)
  137. {
  138.   GLint P[2];
  139.   GLuint point_cnt;
  140.  
  141.   /* translate GLUT into GL coordinates */
  142.   P[0] = x1;
  143.   P[1] = height - y1;
  144.   point_cnt = contours[contour_cnt].point_cnt;
  145.   contours[contour_cnt].p[point_cnt][0] = P[0];
  146.   contours[contour_cnt].p[point_cnt][1] = P[1];
  147.   glBegin(GL_LINES);
  148.   if (point_cnt) {
  149.     glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
  150.     glVertex2iv(P);
  151.   } else {
  152.     glVertex2iv(P);
  153.     glVertex2iv(P);
  154.   }
  155.   glEnd();
  156.   glFlush();
  157.   ++(contours[contour_cnt].point_cnt);
  158.   if (contours[contour_cnt].point_cnt >= MAX_POINTS) {
  159.     printf("Too many points specified.\n");
  160.     exit(1);
  161.   }
  162. }
  163.  
  164. /* ARGSUSED */
  165. void 
  166. middle_down(int x1, int y1)
  167. {
  168.   GLuint point_cnt;
  169.  
  170.   point_cnt = contours[contour_cnt].point_cnt;
  171.   if (point_cnt > 2) {
  172.     glBegin(GL_LINES);
  173.     glVertex2iv(contours[contour_cnt].p[0]);
  174.     glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
  175.     contours[contour_cnt].p[point_cnt][0] = -1;
  176.     glEnd();
  177.     glFlush();
  178.     contour_cnt++;
  179.     if (contour_cnt >= MAX_CONTOURS) {
  180.       printf("Too many contours specified.\n");
  181.       exit(1);
  182.     }
  183.     contours[contour_cnt].point_cnt = 0;
  184.   }
  185. }
  186.  
  187. void 
  188. mouse_clicked(int button, int state, int x, int y)
  189. {
  190.   x += HALF_WIDTH;
  191.   y += HALF_WIDTH;
  192.   x -= x % (2*HALF_WIDTH);
  193.   y -= y % (2*HALF_WIDTH);
  194.   switch (button) {
  195.   case GLUT_LEFT_BUTTON:
  196.     if (state == GLUT_DOWN)
  197.       left_down(x, y);
  198.     break;
  199.   case GLUT_MIDDLE_BUTTON:
  200.     if (state == GLUT_DOWN)
  201.       middle_down(x, y);
  202.     break;
  203.   }
  204. }
  205.  
  206. void 
  207. display(void)
  208. {
  209.   GLint i, j;
  210.   int point_cnt;
  211.  
  212.   glClear(GL_COLOR_BUFFER_BIT);
  213.   switch (mode) {
  214.   case DEFINE:
  215.     /* draw grid */
  216.     glColor3f(0.6, 0.5, 0.5);
  217.     glBegin(GL_LINES);
  218.     for (i = 0; i < width; i += (2*HALF_WIDTH)) {
  219.         glVertex2i(i, height);
  220.         glVertex2i(i, 0);
  221.     }
  222.     for (j = 0; j < height; j += (2*HALF_WIDTH)) {
  223.         glVertex2i(0, j);
  224.         glVertex2i(width, j);
  225.     }
  226.     glColor3f(1.0, 1.0, 0.0);
  227.     for (i = 0; i <= contour_cnt; i++) {
  228.       point_cnt = contours[i].point_cnt;
  229.       glBegin(GL_LINES);
  230.       switch (point_cnt) {
  231.       case 0:
  232.         break;
  233.       case 1:
  234.         glVertex2iv(contours[i].p[0]);
  235.         glVertex2iv(contours[i].p[0]);
  236.         break;
  237.       case 2:
  238.         glVertex2iv(contours[i].p[0]);
  239.         glVertex2iv(contours[i].p[1]);
  240.         break;
  241.       default:
  242.         --point_cnt;
  243.         for (j = 0; j < point_cnt; j++) {
  244.           glVertex2iv(contours[i].p[j]);
  245.           glVertex2iv(contours[i].p[j + 1]);
  246.         }
  247.         if (contours[i].p[j + 1][0] == -1) {
  248.           glVertex2iv(contours[i].p[0]);
  249.           glVertex2iv(contours[i].p[j]);
  250.         }
  251.         break;
  252.       }
  253.       glEnd();
  254.     }
  255.     glFlush();
  256.     break;
  257.   case TESSELATED:
  258.     /* draw lines */
  259.     tesse();
  260.     break;
  261.   }
  262.  
  263.   glColor3f(1.0, 1.0, 0.0);
  264. }
  265.  
  266. void 
  267. clear(void)
  268. {
  269.   contour_cnt = 0;
  270.   contours[0].point_cnt = 0;
  271.   glutMouseFunc(mouse_clicked);
  272.   mode = DEFINE;
  273.   display();
  274. }
  275.  
  276. void 
  277. quit(void)
  278. {
  279.   exit(0);
  280. }
  281.  
  282. void 
  283. menu_selected(int entry)
  284. {
  285.   switch (entry) {
  286.   case CLEAR:
  287.     clear();
  288.     break;
  289.   case TESSELATE:
  290.     tesse();
  291.     break;
  292.   case QUIT:
  293.     quit();
  294.     break;
  295.   }
  296. }
  297.  
  298. /* ARGSUSED1 */
  299. void 
  300. key_pressed(unsigned char key, int x, int y)
  301. {
  302.   switch (key) {
  303.   case 't':
  304.   case 'T':
  305.     tesse();
  306.     glFlush();
  307.     break;
  308.   case 'q':
  309.   case 'Q':
  310.     quit();
  311.     break;
  312.   case 'c':
  313.   case 'C':
  314.     clear();
  315.     break;
  316.   }
  317. }
  318.  
  319. void 
  320. myinit(void)
  321. {
  322.   /* clear background to gray */
  323.   glClearColor(0.4, 0.4, 0.4, 0.0);
  324.   glShadeModel(GL_FLAT);
  325.  
  326.   menu = glutCreateMenu(menu_selected);
  327.   glutAddMenuEntry("clear", CLEAR);
  328.   glutAddMenuEntry("tesselate", TESSELATE);
  329.   glutAddMenuEntry("quit", QUIT);
  330.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  331.   glutMouseFunc(mouse_clicked);
  332.   glutKeyboardFunc(key_pressed);
  333.   contour_cnt = 0;
  334.   glPolygonMode(GL_FRONT, GL_FILL);
  335.   mode = DEFINE;
  336. }
  337.  
  338. static void 
  339. reshape(GLsizei w, GLsizei h)
  340. {
  341.   glViewport(0, 0, w, h);
  342.   glMatrixMode(GL_PROJECTION);
  343.   glLoadIdentity();
  344.   glOrtho(0.0, (GLdouble) w, 0.0, (GLdouble) h, -1.0, 1.0);
  345.   glMatrixMode(GL_MODELVIEW);
  346.   glLoadIdentity();
  347.   set_screen_wh(w, h);
  348. }
  349.  
  350. static void 
  351. usage(void)
  352. {
  353.   printf("Use left mouse button to place vertices.\n");
  354.   printf("Press middle mouse button when done.\n");
  355.   printf("Select tesselate from the pop-up menu.\n");
  356. }
  357.  
  358. /*  Main Loop
  359.  *  Open window with initial window size, title bar, 
  360.  *  RGBA display mode, and handle input events.
  361.  */
  362. int 
  363. main(int argc, char **argv)
  364. {
  365.   usage();
  366.   glutInitWindowSize(400, 400);
  367.   glutInit(&argc, argv);
  368.   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  369.   glutCreateWindow(argv[0]);
  370.   myinit();
  371.   glutDisplayFunc(display);
  372.   glutReshapeFunc(reshape);
  373.   glutMainLoop();
  374.   return 0;             /* ANSI C requires main to return int. */
  375. }
  376.  
  377.